/* main.c */

#include "app_inc.h"
#include "fsl_edma.h"


#define ADC0_CMD_ADDR        (uint32_t)(&(ADC0->SC1[0]))
#define ADC0_DATA_ADDR       (uint32_t)(&(ADC0->R[0]))

/* User-defined Conversion Cmd. */
volatile uint32_t gAppAdcCmd[] =
{
    ADC_SC1_ADCH(0),
    ADC_SC1_ADCH(23),
    ADC_SC1_ADCH(26),
    ADC_SC1_ADCH(27),
    ADC_SC1_ADCH(0),
    ADC_SC1_ADCH(23),
    ADC_SC1_ADCH(26),
    ADC_SC1_ADCH(27) 
};
#define APP_ADC_CMD_COUNT  (sizeof(gAppAdcCmd)/sizeof(gAppAdcCmd[0]))
#define APP_ADC_RECORD_SAMPLE_TIME  10U /* Record multiple time of each conversion. */
#define APP_ADC_DATA_COUNT (APP_ADC_CMD_COUNT * APP_ADC_RECORD_SAMPLE_TIME)

/* User-defined Conversion Data, where keeps the conversion result. */
volatile uint32_t gAppAdcData[APP_ADC_DATA_COUNT];

#define APP_DMA0_CONFIG {                                           \
    .SrcAddr = (uint32_t)gAppAdcCmd,                                \
    .DestAddr = ADC0_CMD_ADDR,                                      \
    .MinorLoopByteCount = sizeof(gAppAdcCmd[0]),                    \
    .SrcBusWidthMode = eEDMA_BusWidth_4Byte,                        \
    .DestBusWidthMode = eEDMA_BusWidth_4Byte,                       \
    .SrcAddrCycleMode = eEDMA_AddrCycle_Disabled,                   \
    .DestAddrCycleMode = eEDMA_AddrCycle_Disabled,                  \
    .SrcAddrIncPerTransfer = (int32_t)(sizeof(gAppAdcCmd[0])),      \
    .DestAddrIncPerTransfer = 0,                                    \
    .SrcAddrMinorLoopDoneOffset = 0,                                \
    .DestAddrMinorLoopDoneOffset = 0,                               \
    .MinorLoopCount = APP_ADC_CMD_COUNT,                            \
    .SrcAddrMajorLoopDoneOffset = -(int32_t)(sizeof(gAppAdcCmd)),   \
    .DestAddrMajorLoopDoneOffset = 0                                \
}

#define APP_DMA1_CONFIG {                                           \
    .SrcAddr = ADC0_DATA_ADDR,                                      \
    .DestAddr = (uint32_t)gAppAdcData,                              \
    .MinorLoopByteCount = sizeof(gAppAdcData[0]),                   \
    .SrcBusWidthMode = eEDMA_BusWidth_4Byte,                        \
    .DestBusWidthMode = eEDMA_BusWidth_4Byte,                       \
    .SrcAddrCycleMode = eEDMA_AddrCycle_Disabled,                   \
    .DestAddrCycleMode = eEDMA_AddrCycle_Disabled,                  \
    .SrcAddrIncPerTransfer = 0,                                     \
    .DestAddrIncPerTransfer = (int32_t)(sizeof(gAppAdcData[0])),    \
    .SrcAddrMinorLoopDoneOffset = 0,                                \
    .DestAddrMinorLoopDoneOffset = 0,                               \
    .MinorLoopCount = APP_ADC_DATA_COUNT,                           \
    .SrcAddrMajorLoopDoneOffset = 0,                                \
    .DestAddrMajorLoopDoneOffset = -(int32_t)(sizeof(gAppAdcData))  \
}


static void APP_InitClockGate(void);
static void APP_InitNvicInterrupts(void);
static void APP_InitAdc(void);
static bool APP_InitEdma(void);
static void APP_InitPit(uint32_t tgrFreqHz);
static void APP_StartPit(void);
static void APP_PausePit(void);

//volatile bool bAppAdcDoneFlag = false;
//volatile uint32_t u32AppAdcValue;

int main(void)
{
    /* Initialize the board. */
    BSP_InitSystem();
    BSP_InitStdioUART(115200);
    
    printf("\r\nHello, World\r\n");

    APP_InitClockGate();
    APP_InitNvicInterrupts();
    APP_InitAdc();
    APP_InitEdma();
    APP_InitPit(2000U);

    printf("\r\nSystem is ready.\r\n");
    
    getchar();
    
    APP_StartPit();
    
    printf("\r\nPress any key to trigger the DMA for ADC Cmd.\r\n");
    
    while (1)
    {
        getchar(); /* Get a trigger from terminal. */
        //EDMA_SwTriggerCmd(0U); /* Trigger the DMA to transfer one ADC Cmd Word. */
        APP_PausePit();
        printf("APP_PausePit()\r\n");
        
        getchar();
        APP_StartPit();
        printf("APP_StartPit()\r\n");
    }
}

static void APP_InitClockGate(void)
{
    SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK
                | SIM_SCGC6_DMAMUX_MASK
                | SIM_SCGC6_PIT_MASK;
    SIM->SCGC7 |= SIM_SCGC7_DMA_MASK;
}

static void APP_InitNvicInterrupts(void)
{
    //NVIC_EnableIRQ(DMA0_IRQn);
    //NVIC_EnableIRQ(ADC0_IRQn);
}

static void APP_InitAdc(void)
{
    ADC0->CFG1 = ADC_CFG1_MODE(1); /* 12-bit resolution. */
    ADC0->CFG2 = 0U;
    ADC0->SC2  = ADC_SC2_DMAEN_MASK; /* To generate DMA request once the conversion is done. */
    ADC0->SC3  = 0U;
}

static bool APP_InitEdma(void)
{
    bool bRet;
    EDMA_TransferConfig_T Edma0Config = APP_DMA0_CONFIG; /* Config the DMA for transfer ADC Cmd. */
    EDMA_TransferConfig_T Edma1Config = APP_DMA1_CONFIG; /* Config the DMA for transfer ADC Cmd. */

    EDMA_ResetEngine();
    
    /*DMA0 for ADC Cmd. */
    DMAMUX_SetTriggerForDMA(0U, eDMAMUX_TriggerSource_Disabled);
    EDMA_ResetChannel(0U);
    bRet = EDMA_ConfigTransfer(0U, &Edma0Config);
    if (!bRet)
    {
        return false;
    }
    EDMA_SetHwTriggerEnabled(0U, true);
    DMAMUX_SetTriggerForDMA(0U, eDMAMUX_TriggerSource_PIT);
    
    /*DMA1 for ADC Data. */
    DMAMUX_SetTriggerForDMA(1U, eDMAMUX_TriggerSource_Disabled);
    EDMA_ResetChannel(1U);
    bRet = EDMA_ConfigTransfer(1U, &Edma1Config);
    if (!bRet)
    {
        return false;
    }
    //EDMA_SetIntEnabledOnMajorLoopDone(1U, true);
    
    EDMA_SetHwTriggerEnabled(1U, true);
    DMAMUX_SetTriggerForDMA(1U, eDMAMUX_TriggerSource_ADC0);
    
    return bRet;
}

static void APP_InitPit(uint32_t tgrFreqHz)
{
    PIT->MCR = PIT_MCR_MDIS_MASK;
    PIT->CHANNEL[0].LDVAL = BSP_CLK_BUSCLK_HZ/tgrFreqHz;
    PIT->CHANNEL[0].TCTRL = 0U; /* The interrupt is disabled, timer is disabled. */
    PIT->CHANNEL[0].TFLG  = PIT_TFLG_TIF_MASK; /* Clear flag. */
    PIT->MCR = 0U; /* Enable the module. */    
}

static void APP_StartPit(void)
{
    PIT->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
}

static void APP_PausePit(void)
{
    PIT->CHANNEL[0].TCTRL &= ~PIT_TCTRL_TEN_MASK;
}

/*
 * IRQs.
 */
#if 0
void ADC0_IRQHandler(void)
{
    u32AppAdcValue = ADC0->R[0]; /* Read result to clear COCO flag. */
    bAppAdcDoneFlag = true;;
}
#endif

/* EOF. */

